/**
 * @file algo_calculus.h
 * @brief Software implementation of Value calculus for 51 microcontroller.
 * @author David Xu &J. Camilo Gomez C.
 * @version 1.0.0
 * @date 2023-11-21
 * @note none
 */

#ifndef ALGO_CALCULUS_H
#define ALGO_CALCULUS_H

// #include <stdint.h>
#include "ct_type.h"
#include "algo_qfp16.h"
#ifdef __cplusplus
extern "C" {
#endif

typedef struct _Cals_state_s {
    /*! @cond  */
    int16_t x[3];
    /*! @endcond  */
} Cals_state_t;


/*! @cond  */
typedef int16_t(code *Cals_Integrat_t)(Cals_state_t *x, const int16_t s, const int16_t dt);
/*! @endcond  */

typedef struct _Cals_Fpstate_s {
    qFP16_t x[3];
} Cals_Fpstate_t;

/*! @cond  */
typedef int16_t(code *Cals_FpIntegrat_t)(Cals_Fpstate_t *x, const qFP16_t s, const qFP16_t dt);
/*! @endcond  */


/**
 * @brief Setup the state object
 * @param[in] x A pointer to the state instance
 * @param[in] sn_1 initial condition at time (t-1)
 * @param[in] sn_2 initial condition at time (t-2)
 * @return none
 */
void Cals_StateInit(Cals_state_t *x, const int16_t x0, const int16_t sn_1, const int16_t sn_2);

/**
 * @brief Perform a numerical integration step by using the rectangular rule.
 * @param[in] x A pointer to the numerical state instance
 * @param[in] s The input signal
 * @param[in] dt The time-step given in seconds.
 * @return The current value of the integration step.
 */
int16_t Cals_IntegralRe(Cals_state_t *x, const int16_t s, const int16_t dt);

/**
 * @brief Perform a numerical integration step by using the trapezoidal rule.
 * @param[in] x A pointer to the numerical state instance
 * @param[in] s The input signal
 * @param[in] dt The time-step given in seconds.
 * @return The current value of the integration step.
 */
int16_t Cals_IntegralTr(Cals_state_t *x, const int16_t s, const int16_t dt);

/**
 * @brief Perform a numerical integration step by using the Simpson's rule.
 * @param[in] x A pointer to the numerical state instance
 * @param[in] s The input signal
 * @param[in] dt The time-step given in seconds.
 * @return The current value of the integration step.
 */
int16_t Cals_IntegralSi(Cals_state_t *x, const int16_t s, const int16_t dt);

/**
 * @brief Perform a numerical derivation step by using the delta rule.
 * @param[in] x A pointer to the numerical state instance
 * @param[in] s The input signal
 * @param[in] dt The time-step given in seconds.
 * @return The current value of the derivation step.
 */
int16_t Cals_Derivative(Cals_state_t *x, const int16_t s, const int16_t dt);


/**
 * @brief Initializes the state of the fixed-point filter.
 * @param[out] x A pointer to the fixed-point state instance to be initialized.
 * @param[in] x0 The initial value for the state.
 * @param[in] sn_1 The initial value for the first previous sample.
 * @param[in] sn_2 The initial value for the second previous sample.
 */
void Cals_FpStateInit(Cals_Fpstate_t *x, const qFP16_t x0, const qFP16_t sn_1, const qFP16_t sn_2);

/**
 * @brief Performs a numerical integration using the rectangle method.
 * @param[in,out] x A pointer to the fixed-point state instance.
 * @param[in] s The input signal to be integrated.
 * @param[in] dt The time-step given in seconds.
 * @return The current value of the integrated state.
 */
qFP16_t Cals_FpIntegralRe(Cals_Fpstate_t *x, const qFP16_t s, const qFP16_t dt);

/**
 * @brief Performs a numerical integration using the trapezoidal rule.
 * @param[in,out] x A pointer to the fixed-point state instance.
 * @param[in] s The input signal to be integrated.
 * @param[in] dt The time-step given in seconds.
 * @return The current value of the integrated state.
 */
qFP16_t Cals_FpIntegralTr(Cals_Fpstate_t *x, const qFP16_t s, const qFP16_t dt);

/**
 * @brief Performs a numerical integration using Simpson's rule.
 * @param[in,out] x A pointer to the fixed-point state instance.
 * @param[in] s The input signal to be integrated.
 * @param[in] dt The time-step given in seconds.
 * @return The current value of the integrated state.
 */
qFP16_t Cals_FpIntegralSi(Cals_Fpstate_t *x, const qFP16_t s, const qFP16_t dt);

/**
 * @brief Calculates the derivative of the input signal with respect to time.
 * @param[in,out] x A pointer to the fixed-point state instance.
 * @param[in] s The input signal whose derivative is to be calculated.
 * @param[in] dt The time-step given in seconds.
 * @return The current value of the derivative.
 */
qFP16_t Cals_FpDerivative(Cals_Fpstate_t *x, const qFP16_t s, const qFP16_t dt);


void test_Cals(void);

#ifdef __cplusplus
}
#endif

#endif
